﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

//int main()
//{
//	int a = 10;
//	printf("%p", &a);
//	//调试取a的地址可以看到&a取出的是a所占4个字节地址
//	//这个代码就是创建了整型变量a，内存申请4个字节用于
//	//存放整数10，每个字节都有地址。
//	return 0;
//}

//int main()
//{
//	int a = 10;
//	int* pa = &a;
//	//取出a的地址存放到指针变量p中
//	printf("%d\n", *pa);
//	//这里pa左边写的是int* ， 
//	//* 是在说明pa是指针变量，
//	//而前面的int是在说明pa指向的是
//	// 整型(int)类型的对象。
//	char ch = 'c';
//	char* pc = &ch;
//	//这里pc左边写的是char* ， 
//	//* 是在说明pc是指针变量，
//	//而前面的char是在说明pc指向的是
//	// 字符型(char)类型的对象。
//	printf("%c\n", *pc);
//	return 0;
//}

//int main()
//{
//	int a = 100;
//	int* pa = &a;
//	*pa = 0;
//	//*pa的意思就是通过pa中存放的地址，找到指向的空间，
//    //*pa其实就是a变量了,所以*pa=0，这个操作符是把a改成了0。
//	printf("%d\n", a);
//	printf("%d\n", *pa);
//	return 0;
//}


//int main()
//{
//	//指针变量的大小取决于地址的大小
//	//32位平台下地址是32个bit位(即4个字节)
//	//64位平台下地址是64个bit位(即8个字节)
//	printf("%zd\n", sizeof(char*));
//	printf("%zd\n", sizeof(short*));
//	printf("%zd\n", sizeof(int*));
//	printf("%zd\n", sizeof(float*));
//	printf("%zd\n", sizeof(double*));
//	return 0;
//}

//int main()
//{
//	int a = 0x11223344;
//	int* pa = &a;
//	*pa = 0;
//	printf("%#x\n", a);  //int*指针的解引用能访问4个字节
//
//	int c = 0x11223344;
//	char* pc = &c;
//	*pc = 0;
//	printf("%#x\n", c);  //而char*指针的解引用只能访问一个字节
//	//这说明指针的类型决定了，对指针解引用的时候就能操作几个字节
//	return 0;
//}


//int main()
//{
//	int a = 10;
//	int* pa = &a;
//	char* pc = (char*)&a;
//	printf("%p\n", &a);        //0093FC70
//	printf("%p\n", pc);		   //0093FC70
//	printf("%p\n", pc+1);	   //0093FC71
//	printf("%p\n", pa);		   //0093FC70
//	printf("%p\n", pa+1);	   //0093FC74
	//char*类型的指针变量+1跳过1个字节。
	//int*类型的指针变量+1跳过了4个字节。
	//这就是指针变量的类型差异带来的变化。
	//指针的类型决定了指针向前或者向后走⼀步有多大(距离)
//	return 0;
//}

//int main()
//{
//	int a = 10;
//	int* pa = &a;
//	char* pc = &a; 
//	//编译器会警告：“初始化”: 从“int *”到“char *”的类型不兼容
//	//这个时候就需要void*指针
//	//它是一种特殊的类型，可以理解为无具体类型的指针(泛型指针)
//	//这种类型的指针可以用来接受任意类型的地址。
//	//void*类型的指针不能直接进行指针的+-整数和解引用运算。
//	return 0;
//}


//int main()
//{
//	int a = 10;
//	char c = 'w';
//	void* pa = &a;
//	void* pc = &c;
//	*pa = 10;
//	*pc = 'z';
//	//这里我们可以看到void*类型的指针可以接收不同类型的地址
//	//但是无法直接进行指针运算
//	//void*类型的指针一般是使用在函数参数的部分
//	//用来接收不同类型数据的地址。
//}


//int main()
//{
//	int a = 0;
//	a = 20;//a可以修改
//	const int b = 0;
//	b = 20;//b不可以修改
//	//这是因为b本质是变量，只不过被const修饰后，在语法上加了限制
//	//只要对b进行修改，就不符合语法规则
//	return 0;
//}

//int main()
//{
//	const int a = 0;
//	printf("a=%d\n", a);
//	int* p = &a;
//	*p = 20;
//	printf("a=%d\n", a);
//	return 0;
//	//但是我们绕过a，使用a的地址，就能修改了。
//	//虽然这样做是打破语法规则，但是我们还是要思考一下，
//	//为什么会a要被const修饰呢？这是为了不能被修改，
//	//如果p拿到a的地址就能修改n，这样就打破了const的限制，
//	//这是不合理的，所以应该让p拿到a的地址也不能修改a。
//}

//void test1()
//{
//	int a = 10;
//	int b = 20;
//	int* p = &a;
//	*p = 20;  //指针p既能修改a的值，也能指向b
//	p = &b;
//}
//void test2()
//{
//	int a = 10;
//	int b = 20;
//	const int* p = &a;
//	//const放在*的左边，修饰的是指针指向的内容
//	//保证指针指向的内容不能通过指针来改变
//	//但是指针变量本身的内容(指向)可变
//	//const int *p等价于int const *p
//	*p = 20;
//	p = &b;
//}
//void test3()
//{
//	int a = 10;
//	int b = 20;
//	int* const p = &a;
//	//const放在*的右边，修饰的是指针变量本身
//	//保证指针变量的内容(指向)不能修改
//	//指针指向的内容可以通过指针改变
//	*p = 20;
//	p = &b;
//}
//void test4()
//{
//	int a = 10;
//	int b = 20;
//	int const* const p = &a;
//	//const放在*的左右两边
//	//即指针指向的内容不能通过指针来改变
//	//指针变量的内容(指向)不能修改
//	*p = 20;
//	p = &b;
//}
//int main()
//{
//	test1();  //测试无const修饰的情况
//	test2();  //测试const放在*左边的情况
//	test3();  //测试const放在*右边的情况
//	test4();  //测试*的左右两边都有const的情况
//	return 0;
//}

//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = &arr;
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	for (i = 0; i < sz; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//	return 0;
//}


//int my_strlen(char *s)
//{
//	char* p = s;
//	while (*p != '\0')
//	{
//		p++;
//	}
//	return p - s;
//}
//int main()
//{
//	printf("%d\n", my_strlen("abcd"));
//	return 0;
//}

//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = arr;
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[10]);
//	while (p < arr + sz)
//	{
//		printf("%d ", *p);
//		p++;
//	}
//	return 0;
//}


//#include <stdio.h>
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = &arr[0];
//	int i = 0;
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	while (p < arr + sz) //指针的大小比较
//	{
//		printf("%d ", *p);
//		p++;
//	}
//	return 0;
//}


//int main()
//{
//	int* p;  //局部变量指针为初始化，默认为随机值
//	// 指向位置不明确
//	*p = 20;
//	return 0;
//}


//int main()
//{
//	int arr[10] = { 0 };
//	int* p = &arr;
//	int i = 0;
//	for (i = 0; i <= 11; i++)
//	{
//		//当指针指向的范围超出数组arr的范围时，p就是野指针
//		*(p++) = i;
//		printf("%d ", *p);
//	}
//	return 0;
//}

//int* test()
//{
//	int a = 100;
//	return &a;
//}
//int main()
//{
//	int* p = test();
//	printf("%d\n", *p);
//	return 0;
//}


//int main()
//{
//	int a = 10;
//	int* p1 = &a;
//	int* p2 = NULL;
//	return 0;
//}


//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = &arr;
//	int i = 0;
//	for (i = 0; i < 5; i++)
//	{
//		*(p++) = 1;
//	}
//	*p = NULL;
//	p = &arr;
//	if (p != NULL)
//	{
//		for (i = 0; i < 10; i++)
//		{
//			printf("%d ", *(p + i));
//		}
//		return 0;
//	}
//
//}

//#include <assert.h>
//int my_strlen(const char* str)
//{
//	int count = 0;
//	assert(str);
//	while (*str)
//	{
//		count++;
//		str++;
//	}
//	return count;
//}
//int main()
//{
//	int len = my_strlen("abcdefghi");
//	printf("%d\n", len);
//	return 0;
//}

//传值调用

//void Swap(int x, int y)
//{
//	int tmp = x;
//	x = y; 
//	y = tmp;
//}
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	printf("交换前：a=%d b=%d", a, b);
//	Swap(a, b);
//	printf("交换后：a=%d b=%d", a, b);
//	return 0;
//}




//传址调用
//void Swap(int* x, int* y)
//{
//	int tmp = *x;
//	*x = *y;
//	*y = tmp;
//}
//int main()
//{
//	int a = 0;
//	int b = 0;
//	scanf("%d %d", &a, &b);
//	printf("交换前：a=%d b=%d", a, b);
//	Swap(&a, &b);
//	printf("交换后：a=%d b=%d", a, b);
//	return 0;
//}

